#!/usr/bin/python

# mail2shell daemon
# $0 user:pass@pop.free.fr ## OBSOLETE
# $0 mail2host.conf

### conf exemple ###
## [General]
## user=pop_user
## password=pop_password
## pop=pop.myisp.tld
## # gpg --list-public-keys --with-colons :
## sender_key=09B14785CC44E886
## smtp=smtp.myisp.tld



import os,sys,email,email.FeedParser,ConfigParser,tempfile,smtplib
from poplib import POP3
from pprint import pprint
import GPG

def getMails(user,passwd,host):
   """return list of messages (email objects)"""
   l=[]
   srv = POP3(host)
   srv.user(user)
   srv.pass_(passwd)
   srv.list()
   (numMsgs, totalSize) = srv.stat()
   for i in range(1, numMsgs + 1):
      (header, msg, octets) = srv.retr(i)
      srv.dele(i)
      fp = email.FeedParser.FeedParser()
      fp.feed("\n".join(msg)+"\n")
      l.append(fp.close())
   srv.quit()
   return l

def displayMails(msgs):
   """Display messages from getMails"""
   for msg in msgs:
      print "From: ",msg['From']
      print "Subject: ",msg['Subject']
      print msg.get_payload()
      print '-----------------------'

def isSigned(msg):
   """check if a message is signed with gpg"""
   if (msg.is_multipart()):
      # arg, mime, not treated
      return {'valid':0}
   obj = GPG.GPGSubprocess()
   sig = obj.verify( msg.get_payload() )
   return sig.__dict__

def addEchos(str):
   "double each command with an echo of it"
   ret=""
   for line in str.split('\n'):
      ret += "echo \"> "+line+"\"\n"+line+"\n"
   return ret

def execCmds (cmds):
   """Execute a list of shell commands"""
   # write commands to temp file
   f = tempfile.NamedTemporaryFile(dir='/tmp/')
   f.write(addEchos(cmds))
   f.flush()
   #~ os.system ("cat "+f.name)
   # exec commands
   (child_stdin, child_stdout_and_stderr) = os.popen4("bash "+f.name)
   return child_stdout_and_stderr.readlines()
   
def sendEmail (server,fro,to,subject,body):
   "send result email"
   msg = ("From: %s\nTo: %s\nSubject: Execution %s\n\n%s"%(fro,to,subject,"".join(body)))
   s = smtplib.SMTP(server)
   #~ s.set_debuglevel(1)
   s.sendmail(fro, to, msg)
   s.quit()

if __name__ == "__main__":
   
   # get user/pass/server ## OBSOLETE
   #~ user=sys.argv[1].split(':')[0]
   #~ passwd=sys.argv[1].split(':')[1].split('@')[0]
   #~ host=sys.argv[1].split('@')[1]
   
   if len(sys.argv) < 2:
      print "usage: %s <config_file>"%sys.argv[0]
      sys.exit(2)
   
   cfg = ConfigParser.ConfigParser()
   cfg.read(sys.argv[1])
   user=cfg.get("General","user")
   passwd=cfg.get("General","password")
   pop_host=cfg.get("General","pop")
   sender_key=cfg.get("General","sender_key")
   smtp_host=cfg.get("General","smtp")

   # get mails and display them
   print "Connection au serveur pop ..."
   msgs = getMails(user,passwd,pop_host)
   print len(msgs)," messages"

   # displayMails(msgs)
   # check validity of messages
   print "Parcours des messages ..."
   for msg in msgs:
      d = isSigned(msg)
      if d['valid'] == 1 and d['key_id'] == sender_key:
         print "Message '%s' valide, execution ..."%(msg['Subject'])
         #~ pprint(d)
         retour = execCmds(d['data'])
         #~ print retour
         sendEmail(smtp_host,msg['To'],msg['From'],msg['Subject'],retour)
      else:
         print "Message '%s' INvalide"%(msg['Subject'])

